from django.shortcuts import render

# Create your views here.
from django_redis import get_redis_connection
import base64
import pickle

from rest_framework.response import Response
from rest_framework.views import APIView

from goods.models import SKU
from .serializer import CartSerializer,CartDeleteSerializer,CartSKUSerializer
class CartView(APIView):
    """
    我们的视图，如果你传递了token就会调用perform_authentication方法进行调用，来验证用户信息
    如果token过期或者被伪造了就不能被添加到购物车了
    所以，让先添加到购物车，也就是说先不调用perform_authentication方法
    """
    def perform_authentication(self, request):
        pass

    def post(self,request):

        # 1.接收数据，并对数据进行校验
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 2.获取对应的数据
        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected')

        # 3.判断用户的登录状态
        try:
            user = request.user
        except Exception:
            user = None
        # 4.登录用户
        if user is not None and user.is_authenticated:
            #     连接redis
            redis_conn = get_redis_connection('cart')
            #     保存数据
            #hash
            # redis_conn.hset('cart_%s'%user.id,sku_id,count)
            # redis_conn.hincrby('cart_%s'%user.id,sku_id,count)
            # #set
            # if selected:
            #     redis_conn.sadd('cart_selectet_%s'%user.id,sku_id)
            # #     返回响应
            pipe = redis_conn.pipeline()

            pipe.hincrby('cart_%s'%user.id,sku_id,count)

            if selected:
                pipe.sadd('cart_selectet_%s'%user.id,sku_id)


            #管道统一执行
            pipe.execute()


            return Response(serializer.data)
        # 5.未登录用户
        else:
        #     读取cookie数据，判断数据是否存在

            cart_str =request.COOKIES.get('cart')

            if cart_str is not None:
                #cart_str　先进行base64解码
                decode = base64.b64decode(cart_str)
                #再将二进制转换为字典
                cart = pickle.loads(decode)
            else:
                cart = {}

            #     更新购物车数据
            if sku_id in cart:
                orginal_count = cart[sku_id]['count']
                count +=orginal_count
            cart[sku_id]={
                'count':count,
                'selected':selected
            }

            #     对字典进行处理

            dumps = pickle.dumps(cart)

            encode = base64.b64encode(dumps)
            new_cart = encode.decode()

            #     返回响应
            response = Response(serializer.data)
            response.set_cookie('cart',new_cart,3600)

            return response

    """
    当用户点击购物车的时候，前端应该发送一个ajax请求给后端, jwt token(在请求体头中)

    1.获取用户信息,根据用户信息判断用户是登录
    2.登录用户redis
        连接redis
        获取数据　hash set
    3.非登录用户
        从cookie中获取数据,并判断数据是否存在

    4.根据数据的id 查询商品的信息
    5.对数据进行序列化操作
    6.返回响应
    """

    def get(self,request):
        # 1.获取用户信息,根据用户信息区判断是否登录
        try:
            user = request.user
        except Exception:
            user = None

        if user is not None and user.is_authenticated:

            # 2.登录用户 redis
            #     2.1 连接redis
            redis_conn = get_redis_connection('cart')
            #     2.2 获取数据 hash  set
            #hash
            sku_count = redis_conn.hgetall('cart_%s'%user.id)
            # {1:4,2:20,3:40}
            # set 选中的id
            selected_ids = redis_conn.smembers('cart_selected_%s'%user.id)
            # [1,2,3]

            # 因为 redis的数据和cookie的数据格式不一致,所以进行序列化操作的时候不统一
            # 我们将 redis的数据格式转换成 cookie的数据格式就可以
            # cart={1:{count:xxx,selected:xxxx},2:{count:xxx,selected:xxxx},3:{count:xxx,selected:xxxx}}
            cart = {}

            # 对 hash数据进行遍历
            for sku_id,count in sku_count.items():

                if sku_id in selected_ids:
                    selected=True
                else:
                    selected=False

                cart[int(sku_id)] = {
                    'count':int(count),
                    # 'selected': sku_id in selected_ids
                    'selected': selected
                }

        else:
            # 3. 未登录用户就是cookie
            #     3.1 从cookie中获取数据,判断数据是否存在

            cookie_str = request.COOKIES.get('cart')
            if cookie_str is not None:
                #有数据
                # 先经过base64解码
                decode = base64.b64decode(cookie_str)
                # 再转换为字典
                cart = pickle.loads(decode)
            else:
                #没有数据
                cart = {}
                # cart={1:{count:xxx,selected:xxxx}}

        # cart={1:{count:xxx,selected:xxxx},2:{count:xxx,selected:xxxx}3:{count:xxx,selected:xxxx}}
        ids = cart.keys()  #[1,2,3,4,5]
        # 4 如果存在数据,我们要根据id 进行商品信息的查询 [SKU,SKU,SKU]
        skus = SKU.objects.filter(pk__in=ids)


        for sku in skus:
            #cart={1:{count:xxx,selected:xxxx}}
            sku.count=cart[sku.id]['count']
            sku.selected=cart[sku.id]['selected']

        # [SKU,SKU,SKU]
        # 5 对数据进行序列化操作
        serializer = CartSKUSerializer(skus,many=True)
        # 6 返回响应
        # 序列化操作的时候 , 序列化操作的原理是: 根据 序列化器的字段 区获取模型中数据
        # 现在模型中没有 count和selected

        return Response(serializer.data)

    """
    修改购物车的逻辑　　前端在修改的时候应该把sku_id,count,selected  token 发送给后端

    1.接收参数，并对参数进行校验
    2.获取数据，sku_id count selected
    3.判断用户登录状态
    4.登录状态redis
        连接redis
        保存数据
        返回响应
    5.未登录用户cookie
        获取cookie数据并对cookie数据进行判断
        修改数据
        cart 需要对字典进行base64处理
        返回响应(必须包含商品的数量)
    """

    def put(self,request):
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected')

        try:
            user = request.user
        except Exception:
            user =  None

        # request.user.is_authenticated
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('cart')
            redis_conn.hset('cart_%s'%user.id,sku_id,count)
            if selected:
                redis_conn.sadd('cart_selected_%s'%user.id,sku_id)
            else:
                redis_conn.srem('cart_selected_%s'%user.id,sku_id)
            return Response(serializer.data)

        else:
            cookie_str = request.COOKIES.get('cart')
            if cookie_str is not None:
                decode = base64.b64decode(cookie_str)
                cart = pickle.loads(decode)
            else:
                cart = {}

            if sku_id in cart:
                cart[sku_id] = {
                    'count':count,
                    'selected':selected
                }
            dumps = pickle.dumps(cart)
            encode = base64.b64encode(dumps)
            new_cart = encode.decode

            response = Response(serializer.data)
            response.set_cookie('cart',new_cart)

            return response

    """
    当用户点击删除按钮的时候，前端应该将sku_id传递给后端

    １.接收参数，并且对参数进行校验
    2.获取sku_id
    3.判断用户登录状态
    4.登录用户redis
        连接redis
        删除hash set
        返回响应
    5.为登录用户cookie
        获取cookie
        删除cookie数据
        对cart进行处理
        返回响应
    """
    def delete(self,request):
        serializer = CartDeleteSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        sku_id = serializer.data.get('sku_id')

        try:
            user = request.user
        except Exception:
            user = None

        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('cart')
            #hash
            redis_conn.hdel('cart_%s'%user.id,sku_id)
            #set
            redis_conn.srem('cart_selected_%s'%user.id,sku_id)

            return Response(serializer.data)
        else:
            cookie_str = request.COOKIES.get('cart')
            if cookie_str is not None:
                cart = pickle.loads(base64.b64decode(cookie_str))
            else:
                cart = {}

            if sku_id in cart:
                del cart[sku_id]

            #对cart进行处理
            new_cart = base64.b64encode(pickle.dumps(cart)).decode()
            response =  Response(serializer.data)
            response.set_cookie('cart',new_cart)
            return response





















